Skip to content

feat(mcp): add proposals section to morning brief#20

Merged
Koopa0 merged 4 commits into
mainfrom
feat/brief-proposals-section
Jul 3, 2026
Merged

feat(mcp): add proposals section to morning brief#20
Koopa0 merged 4 commits into
mainfrom
feat/brief-proposals-section

Conversation

@Koopa0

@Koopa0 Koopa0 commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add a proposals section to brief(mode=morning) exposing proposals_pending — the summed count of agent-proposed area/goal/project drafts awaiting owner triage. This lets the hermes push agent read the triage backlog over the MCP surface (its existing access path) to decide whether to nudge Koopa back to the admin triage queue, instead of holding admin API credentials just to read the count.
  • Fix a pre-existing doc drift: the morning sections filter key was documented as tasks in three agent-facing places, but the code matches the runSection label todos, so an agent following the docs passed an unmatched key and silently received an empty briefing. Corrected in the catalog tool description, the BriefInput schema tag, and the skills manual, and completed the todos-section field list (adds active_todos, plus recurring_todos in the manual).

Design notes

  • proposals_pending is a scalar on the morning wire (always emitted, 0 when nothing is pending); the consumer gates its nudge on N > 0. It is never emitted in reflection mode.
  • fillProposalsPending reads the goal and project proposed-counts independently; each degrades to its own zero on error (matching the sibling section fillers), so a transient failure undercounts rather than suppressing the whole nudge signal.
  • Read-only: no new write path, no schema/migration change, tool count stays 15.
  • The generated tool-inventory block is unchanged (brief's first sentence is unaffected); only the hand-written section docs changed.

Test Plan

  • go build ./... && go vet ./... && golangci-lint run ./internal/mcp/... — clean (0 issues)
  • go test ./... — all unit tests pass, including the ops drift test (TestToolInventoryDocInSync) and new TestBriefOutput_ProposalsPendingWire
  • go test -tags=integration ./internal/mcp/ — full suite passes, including new TestIntegration_BriefMorning_ProposalsPending (asserts the sum across all three proposed-entity kinds plus the section-filter wiring)

Consumer-side spec (for the hermes repo) lives in docs/hermes-proposals-push-spec.md; it is not part of this PR's code.

Koopa0 added 2 commits July 3, 2026 10:11
The brief tool's morning `sections` filter matches the runSection label
"todos", but three agent-facing docs advertised the key as 'tasks', so an
agent following them passed an unmatched key and silently received an empty
briefing. Correct the key in the catalog tool description, the BriefInput
schema tag, and the skills manual, and complete the todos-section field list
(add active_todos, plus recurring_todos in the manual) so the enumerated
fields match what the section actually emits. Documentation only; no
behaviour change.
Expose proposals_pending — the summed count of agent-proposed area, goal, and
project drafts awaiting owner triage — as a new "proposals" section on
brief(mode=morning). This lets the hermes push agent read the triage backlog
over the MCP surface (its existing access path) to decide whether to nudge
Koopa back to the admin triage queue, instead of holding admin API credentials
just to read the count.

proposals_pending is a scalar on the morning wire (always emitted, 0 when
nothing is pending); the consumer gates its nudge on N > 0. fillProposalsPending
reads the goal and project proposed-counts independently and each degrades to
its own zero on error: a transient failure on one entity undercounts rather
than suppressing the whole signal, which for a "don't let the queue rot" nudge
is the safer failure mode than all-or-nothing.

Covered by a morning-wire unit test and an integration test asserting the sum
across all three proposed-entity kinds plus the section-filter wiring.
@augmentcode

augmentcode Bot commented Jul 3, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: Adds a proposals backlog signal to the MCP morning brief and fixes agent-facing docs around the morning sections filter.

Changes:

  • Extend brief(mode=morning) with proposals_pending, the summed count of proposed areas + goals + projects awaiting owner triage.
  • Add a new morning section key proposals to compute/populate that count.
  • Fix documentation/schema/catalog drift: the todos section key is todos (not tasks), and the todos field list includes active_todos.
  • Add unit coverage to pin proposals_pending as an always-present scalar in morning mode and absent in reflection mode.
  • Add an integration test to verify summing across all proposal kinds and correct section-filter wiring.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread internal/mcp/brief.go Outdated
} else {
s.logger.Warn("brief: proposed projects count", "error", err)
}
out.ProposalsPending = int(total)

@augmentcode augmentcode Bot Jul 3, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal/mcp/brief.go:428 casts the summed proposal counts from int64 to int; if the counts ever exceed math.MaxInt (or on 32-bit builds), this can silently overflow and produce an incorrect proposals_pending signal.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread internal/mcp/brief.go
As string `json:"as,omitempty" jsonschema_description:"Caller agent identity (e.g. koopa0-dev)."`
Mode string `json:"mode" jsonschema_description:"Briefing mode (required): 'morning' = daily-planning pull (todos/goals/rss/content_pipeline); 'reflection' = end-of-day plan-vs-actual retrospective (daily plan items + completion counts). brief is a pure planning-state pull and carries no agent memory."`
Sections FlexStringSlice `json:"sections,omitempty" jsonschema_description:"MORNING-ONLY strict filter on which groups to populate (default: all). Ignored in reflection mode. Omit or pass [] to get the full morning briefing. Group key → response fields: 'tasks' → overdue_todos/today_todos/recurring_todos/committed_todos/upcoming_todos; 'goals' → active_goals; 'rss' → rss_highlights; 'content_pipeline' → content_pipeline. Unknown keys silently ignored."`
Sections FlexStringSlice `json:"sections,omitempty" jsonschema_description:"MORNING-ONLY strict filter on which groups to populate (default: all). Ignored in reflection mode. Omit or pass [] to get the full morning briefing. Group key → response fields: 'todos' → overdue_todos/today_todos/active_todos/recurring_todos/committed_todos/upcoming_todos; 'goals' → active_goals; 'rss' → rss_highlights; 'content_pipeline' → content_pipeline; 'proposals' → proposals_pending (count of agent-proposed area/goal/project drafts awaiting owner triage). Unknown keys silently ignored."`

@augmentcode augmentcode Bot Jul 3, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal/mcp/brief.go:84 documents sections as a strict filter, but proposals_pending is always emitted as a scalar (so callers filtering out proposals will still see proposals_pending: 0). Consider clarifying this in the tool/schema description so consumers don’t misread 0 as an explicitly computed value.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread internal/mcp/ops/catalog.go Outdated
Stability: StabilityStable,
Since: since,
Description: "Read-only planning-state pull. Pick a mode (required): 'morning' = single-call daily-planning briefing (overdue/today/recurring/committed/upcoming todos, active_goals, rss_highlights, content_pipeline); 'reflection' = end-of-day plan-vs-actual retrospective (planned_items + completed/deferred/planned counts + completion_rate). brief is a pure planning-state pull and carries no agent memory. Morning mode is filterable via the sections parameter (ignored in reflection mode) — valid keys (omit or pass [] for all): 'tasks' (overdue/today/recurring/committed/upcoming todos), 'goals' (active_goals), 'rss' (rss_highlights — feeds tagged priority=high, NOT relevance-ranked; use search_knowledge for ranked retrieval), 'content_pipeline' (content_pipeline). Every caller gets all sections by default; pass an explicit sections list to narrow the briefing. Scope is the target date (default today), not since-last-session.",
Description: "Read-only planning-state pull. Pick a mode (required): 'morning' = single-call daily-planning briefing (overdue/today/recurring/committed/upcoming todos, active_goals, rss_highlights, content_pipeline); 'reflection' = end-of-day plan-vs-actual retrospective (planned_items + completed/deferred/planned counts + completion_rate). brief is a pure planning-state pull and carries no agent memory. Morning mode is filterable via the sections parameter (ignored in reflection mode) — valid keys (omit or pass [] for all): 'todos' (overdue/today/active/recurring/committed/upcoming todos), 'goals' (active_goals), 'rss' (rss_highlights — feeds tagged priority=high, NOT relevance-ranked; use search_knowledge for ranked retrieval), 'content_pipeline' (content_pipeline), 'proposals' (proposals_pending — count of agent-proposed area/goal/project drafts awaiting owner triage). Every caller gets all sections by default; pass an explicit sections list to narrow the briefing. Scope is the target date (default today), not since-last-session.",

@augmentcode augmentcode Bot Jul 3, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal/mcp/ops/catalog.go:35’s top-level morning description still lists the todos set without mentioning active_todos (and doesn’t mention proposals_pending at all), which can drift from the actual morning wire shape for clients that only read the opening summary.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Koopa0 added 2 commits July 3, 2026 10:31
…narrowing

The proposed area/goal/project counts come from count(*) (int64); summing them
into an int field required an int64->int conversion that narrows on 32-bit
builds. The counts are far too small to overflow in practice, but typing the
field as int64 matches the source and removes the conversion entirely rather
than guarding an impossible case. No behaviour or wire change — JSON still
serialises a bare number.

Addresses Augment review on PR #20.
The opening morning summaries — in the brief tool description, the mode schema
tag, and the skills manual — still listed the pre-proposals section set and
omitted active_todos, drifting from what the morning wire actually emits. List
active_todos and proposals_pending everywhere the sections are summarised, and
correct the BriefInput doc's "empty-slice default" wording to "zero-value
default" now that proposals_pending is a scalar (0), noting that an unrequested
field's default is not a computed result.

Addresses Augment review on PR #20.
@Koopa0 Koopa0 merged commit 33e70e8 into main Jul 3, 2026
5 checks passed
@Koopa0 Koopa0 deleted the feat/brief-proposals-section branch July 3, 2026 02:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant